package com.example.waterfall.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import com.example.waterfall.BuildConfig;
import com.example.waterfall.cache.DiskLruCache;
import com.example.waterfall.cache.ImageCache;
import com.nostra13.universalimageloader.core.assist.FlushedInputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.widget.Toast;

/**
 * 图片帮助类，用以获取图片（缓存，本地，网络)
 * 
 * @author huangrongcai
 * 
 */
public class ImageFetcher extends ImageResizer {
	private static final String TAG = "ImageFetcher";
	/** 缓存前缀 */
	public static final String HTTP_CACHE_DIR = "http";
	/** 磁盘缓存大小10M */
	private static final int HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10MB
	private ImageCache imageCache;
	private DiskLruCache diskLruCache;
	protected Handler mHandler;

	/**
	 * 默认构造
	 */
	public ImageFetcher(Context context, Handler handler) {
		super(context, handler);
		init();
	}
	/**
	 * 
	 * @param context
	 */
	public ImageFetcher(Context context) {
		super(context,null);
		init();
	}

	/**
	 * 初始化
	 */
	private void init() {
		this.diskLruCache = getDiskCache();
		this.imageCache = ImageCache.getInstance(null);
		setImageCache(imageCache);
	}

	@Override
	protected Bitmap processBitmap(Object data) {
		Bitmap bitmap = null;
		String key = String.valueOf(data);
		if (bitmap == null) {
			bitmap = getFromMemery(key);
		}
		if (bitmap == null) {
			bitmap = getFromDisk(key);
		}

		if (bitmap == null) {
			bitmap = getFromNetwork(key);
		}

		if (key != null && bitmap != null) {
			imageCache.put(key, bitmap);
		}
		// 磁盘缓存
		return bitmap;
	}

	/**
	 * 获取图片
	 * 
	 * @param key
	 * @return
	 */
	private Bitmap get(String key) {
		return null;
	}

	/**
	 * 从内存获取
	 * 
	 * @param key
	 * @return
	 */
	private Bitmap getFromMemery(String key) {
		Log.d(TAG, "getFromMemery");
		return imageCache.get(key);
	}

	/**
	 * 从磁盘获取
	 * 
	 * @param key
	 * @return
	 */
	private Bitmap getFromDisk(String key) {
		Log.d(TAG, "getFromDisk");
		if (diskLruCache.containsKey(key)) {
			File cacheFile = new File(diskLruCache.createFilePath(key));
			return decodeSampledBitmapFromFile(cacheFile.toString(),
					mImageWidth, mImageHeight);
		}
		return null;

	}

	/**
	 * 获取或创建缓存文件
	 * 
	 * @param key
	 * @return
	 */
	private DiskLruCache getDiskCache() {
		final File cacheDir = DiskLruCache.getDiskCacheDir(mContext,
				HTTP_CACHE_DIR);
		final DiskLruCache cache = DiskLruCache.openCache(mContext, cacheDir,
				HTTP_CACHE_SIZE);
		return cache;

	}

	private File getCacheDir() {
		return DiskLruCache.getDiskCacheDir(mContext, HTTP_CACHE_DIR);
	}

	/**
	 * 负责下载网络数据
	 * 
	 * @param key
	 * @return
	 */
	private Bitmap getFromNetwork(String key) {
		Log.d(TAG, "getFromNetwork");
		String imageUrl = key;
		// 检查网络（网络不通）
		// 检查磁盘（磁盘不足）磁盘缓存做检查
		// 网速监听（网束不行）networkutil
		// 连接超时
		// 请求超时
		Bitmap bitmap = null;
		if (isAvailableConnect(mContext)) {
			Utils.disableConnectionReuseIfNecessary();
			// 检查空间
			if (true) {
				// 如果空间够，则下载到磁盘,优先下载到磁盘
				BufferedInputStream inStream = getInputStreamFromUrl(imageUrl,
						0);
				File cacheFile = new File(diskLruCache.createFilePath(imageUrl));
				writeFile(inStream, cacheFile);
				bitmap = decodeSampledBitmapFromFile(cacheFile.toString(),
						mImageWidth, mImageHeight);
			} else {
				// 如果空间不够，则直接解析流，获取图片。
				// 保证即使用房磁盘不足，也能够看到图片。但会消流量
				BufferedInputStream inStream = getInputStreamFromUrl(imageUrl,
						0);
				// 解析流到内存
				bitmap = decodeSampledBitmapFromStream(inStream, mImageWidth,
						mImageHeight);
			}
		}
		// 解析文件成图片
		if (bitmap != null) {
			return bitmap;
		}
		// 返回图片
		return null;
	}

	/**
	 * 写到文件,即写入到磁盘缓存
	 * 
	 * @return 返回写好的文件
	 */
	private File writeFile(InputStream in, File cacheFile) {
		// 效率必改
		BufferedOutputStream out = null;
		in = new FlushedInputStream(in);
		try {
			out = new BufferedOutputStream(new FileOutputStream(cacheFile),
					Utils.IO_BUFFER_SIZE);
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}

			return cacheFile;

		} catch (final IOException e) {
			// 作检查，看看是不是磁盘空间不足
			Log.e(TAG, "Error in downloadBitmap - " + e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (final IOException e) {
					Log.e(TAG, "Error in downloadBitmap - 写文件错误" + e);
					// showToast(mContext,"磁盘空间不足，检查");
				}
			}
		}
		return null;

	}

	/**
	 * 获取输入流
	 * 
	 * @param imageUrl
	 * @param readTimeOutMillis
	 *            读写超时，<0则无读写超时
	 * @return
	 */
	public BufferedInputStream getInputStreamFromUrl(String imageUrl,
			int readTimeOutMillis) {
		BufferedInputStream inputStream = null;
		try {
			final URL url = new URL(imageUrl);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			if (readTimeOutMillis > 10) {
				con.setReadTimeout(readTimeOutMillis);
			}
			inputStream = new BufferedInputStream(con.getInputStream(),
					Utils.IO_BUFFER_SIZE);
		} catch (Exception e) {
			closeInputStream(inputStream);
		}
		return inputStream;
	}

	/**
	 * close inputStream
	 * 
	 * @param s
	 */
	private static void closeInputStream(InputStream s) {
		if (s == null) {
			return;
		}
		try {
			s.close();
		} catch (IOException e) {
			throw new RuntimeException("IOException occurred. ", e);
		}
	}

	/**
	 * 连接是否可用
	 * 
	 * @param mContext
	 * @return true 可用
	 */
	private boolean isAvailableConnect(Context mContext) {
		if (NetworkUtil.isAvailable(mContext)) {
			return true;
		}
		return false;

	}

	// 引用缓存，下载，磁盘

	@Override
	public void setLoadingImage(int emptyPhoto) {
		super.setLoadingImage(emptyPhoto);
	}

	private void showToast(Context context, String msg) {
		Looper.prepare();
		Toast.makeText(mContext, msg, 0).show();
		Looper.loop();

	}

}
